package com.passion.solr.util;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.extractor.WordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;

/**
 * 类描述：文件读取工具类
 *
 * @author ZhuYin
 * @since 2024年12月03日
 */
@Slf4j
public class FileUtil {
    /**
     * 读取文档内容
     * 目前仅支持 txt, doc, docx, pdf 格式
     *
     * @param file 文件对象
     * @return 文档内容
     */
    public static String readFileContent(MultipartFile file) {
        String filename = file.getOriginalFilename();
        assert filename != null;
        String fileType = filename.substring(filename.lastIndexOf(".") + 1).toUpperCase();
        switch (fileType) {
            case "TXT":
                return readTxtContent(file);
            case "DOC":
            case "DOCX":
                return readWordContent(file);
            case "PDF":
                return readPDFContent(file);
            default:
                return "";
        }
    }

    /**
     * 读取 txt 文档内容
     */
    private static String readTxtContent(MultipartFile file) {
        try {
            return StrUtil.utf8Str(file.getBytes());
        } catch (IOException e) {
            log.error("读取 txt 文件内容时发生 IO 异常:", e);
            return "";
        }
    }

    /**
     * 读取 doc 和 docx 文档内容
     */
    private static String readWordContent(MultipartFile file) {

        String filename = file.getOriginalFilename();
        assert filename != null;
        String fileType = filename.substring(filename.lastIndexOf(".") + 1);
        return "doc".equals(fileType) ? readDocContent(file) : readDocxContent(file);
    }

    /**
     * 读取 .doc 格式的 word 文档
     *
     * @param file 文件对象
     * @return 文本内容
     */
    private static String readDocContent(MultipartFile file) {
        StringBuilder content = new StringBuilder();
        try (InputStream inputStream = file.getInputStream();
             HWPFDocument document = new HWPFDocument(inputStream)) {
            WordExtractor extractor = new WordExtractor(document);
            String[] paragraphs = extractor.getParagraphText();
            for (String paragraph : paragraphs) {
                content.append(paragraph);
            }
        } catch (IOException e) {
            log.error("读取文件内容时发生 IO 异常:", e);
        }
        return content.toString();
    }

    /**
     * 读取 .docx 格式的 word 文档
     *
     * @param file 文件对象
     * @return 文本内容
     */
    private static String readDocxContent(MultipartFile file) {
        StringBuilder content = new StringBuilder();
        try (InputStream inputStream = file.getInputStream();
             XWPFDocument document = new XWPFDocument(inputStream)) {
            for (XWPFParagraph paragraph : document.getParagraphs()) {
                for (XWPFRun run : paragraph.getRuns()) {
                    String runText = run.getText(0);
                    if (runText != null) {
                        content.append(runText);
                    }
                }
            }
        } catch (IOException e) {
            log.error("读取文件内容时发生 IO 异常:", e);
        }
        return content.toString();
    }

    /**
     * 读取 pdf 文档内容
     */
    private static String readPDFContent(MultipartFile file) {
        StringBuilder content = new StringBuilder();
        try (InputStream inputStream = file.getInputStream();
             PDDocument document = PDDocument.load(inputStream)) {
            // 检查是否是由文档转换出的 pdf 文件
            if (!document.isEncrypted() && document.getNumberOfPages() > 0) {
                PDFTextStripper textStripper = new PDFTextStripper();
                content.append(textStripper.getText(document));
            } else {
                log.warn("PDF 已加密或不是由文档转换的 PDF 格式，无法读取内容！");
            }
        } catch (IOException e) {
            log.error("读取文件内容时发生 IO 异常:", e);
        }
        return content.toString();
    }
}

